home *** CD-ROM | disk | FTP | other *** search
- /*-
- * $Id: hanmain.c,v 1.30 90/06/04 23:16:50 Rhialto Rel $
- * $Log: hanmain.c,v $
- * Revision 1.30 90/06/04 23:16:50 Rhialto
- * Release 1 Patch 3
- *
- * HANMAIN.C
- *
- * The code for the messydos file system handler.
- *
- * Some start/stop stuff that is not really part of the
- * file system itself but that must be done anyway.
- *
- * This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
- * not be used or copied without a licence.
- -*/
-
- #include "dos.h"
- #include "han.h"
-
- #ifdef HDEBUG
- # define debug(x) dbprintf x
- #else
- # define debug(x)
- #endif
-
- extern int CheckBootBlock;
- extern char DotDot[1 + 8 + 3];
- struct Library *IntuitionBase;
- static char RCSId[] = "Messydos filing system $Revision: 1.30 $ $Date: 90/06/04 23:16:50 $, by Olaf Seibert";
-
- byte
- ToUpper(ch)
- register byte ch;
- {
- if (ch >= 'a' && ch <= 'z')
- return ch + ('A' - 'a');
- if (ch == '.')
- return '!';
- return ch & ~DIR_DELETED_MASK;
- }
-
- long
- lmin(a, b)
- long a,
- b;
- {
- return (a < b) ? a : b;
- }
-
- byte *
- ZapSpaces(begin, end)
- register byte *begin,
- *end;
- {
- while (end > begin && end[-1] == ' ')
- *--end = '\0';
-
- return end;
- }
-
- /*
- * Map an arbitrary file name to MS-DOS conventions. The output format is
- * 8+3 without dot, padded with spaces, suitable for direct comparison
- * with directory entries. Return a pointer to the delimiter found ('\0'
- * or '/'). [[Make sure that Examine/ExNext return a proper inverse of
- * this...]]
- */
-
- byte *
- ToMSName(dest, source)
- byte *dest;
- register byte *source;
- {
- byte *dotp;
- byte *slashp;
- register int i,
- len;
-
- if (*source == '/') { /* parentdir */
- strncpy(dest, DotDot, 8 + 3); /* ".." */
- return source;
- }
- /*
- * Remove any strictly leading dots. .info -> info, .indent.pro ->
- * indent.pro, .profile -> profile, etc.
- */
- while (*source == '.')
- source++;
-
- /*
- * Find dot and slash which are delimiters of name and extension.
- */
- {
- register byte *cp;
-
- cp = source;
- while (*cp) {
- if (*cp == '.' || *cp == '/')
- break;
- cp++;
- }
- dotp = cp;
- while (*cp) {
- if (*cp == '/')
- break;
- cp++;
- }
- slashp = cp;
- }
-
- len = dotp - source;
- if (len > 8)
- len = 8;
-
- for (i = 0; i < len; i++) {
- *dest++ = ToUpper(*source++);
- }
- for (; i < 8; i++) {
- *dest++ = ' ';
- }
-
- source = dotp + 1;
- len = slashp - source; /* so will be -1 if no suffix */
- if (len > 3)
- len = 3;
-
- for (i = 0; i < len; i++) {
- *dest++ = ToUpper(*source++);
- }
- for (; i < 3; i++) {
- *dest++ = ' ';
- }
-
- return slashp;
- }
-
- /*
- * Do the Info call.
- */
-
- long
- MSDiskInfo(infodata)
- struct InfoData *infodata;
- {
- extern DEVLIST *VolNode;
-
- setmem(infodata, sizeof (*infodata), 0);
-
- infodata->id_DiskState = IDDiskState;
- infodata->id_DiskType = IDDiskType;
- infodata->id_UnitNumber = UnitNr;
-
- infodata->id_VolumeNode = (BPTR) CTOB(VolNode);
- infodata->id_InUse = LockList ? 1 : 0;
-
- if (IDDiskType == ID_DOS_DISK) {
- infodata->id_NumBlocks = Disk.nsects;
- infodata->id_NumBlocksUsed = Disk.nsects - Disk.nsectsfree;
- infodata->id_BytesPerBlock = Disk.bps;
- }
- return DOSTRUE;
- }
-
- /*
- * We (re-)establish our List of MSFileLocks after a disk has been
- * (re-)inserted. If there are no known locks, we make the root lock from
- * the volume label, if there is one.
- *
- * We get a special cookie to hand to a cleanup routine that we must call
- * when finally all locks on the current disk are UnLock()ed. (this is
- * actually the volume node, but we don't want to know that.)
- *
- * This must be called some time after IdentifyDisk().
- */
-
- void
- MSDiskInserted(locks, cookie)
- register struct LockList **locks;
- void *cookie;
- {
- debug(("MSDiskInserted %08lx\n", cookie));
-
- LockList = *locks;
-
- if (LockList == NULL) {
- LockList = NewLockList(cookie);
- RootLock = MakeLock(NULL, &Disk.vollabel, SHARED_LOCK);
- } else {
- RootLock = MSDupLock(GetTail(&LockList->ll_List));
- }
-
- InitCacheList();
- }
-
- /*
- * Remove the current disk. A place is offered to save the current
- * LockList to restore later. We must unlock the root lock since it isn't
- * a real reference to the disk, just a placeholder for dummies that hand
- * us NULL locks.
- */
-
- int
- MSDiskRemoved(locks)
- register struct LockList **locks;
- {
- #ifndef READONLY
- if (FatDirty || (DelayState & DELAY_DIRTY))
- MSUpdate(1); /* Force a requester */
- #endif
-
- FreeFat();
- FreeCacheList();
-
- IDDiskType = ID_NO_DISK_PRESENT;
- *locks = NULL;
-
- if (RootLock == NULL) {
- debug(("MSDiskRemoved with no RootLock\n"));
- return 1;
- }
- #ifdef HDEBUG
- if (RootLock != GetTail(&LockList->ll_List)) {
- debug(("RootLock not at end of LockList!\n"));
- /* Get the lock on the root dir at the tail of the List */
- Remove(RootLock);
- AddTail(&LockList->ll_List, RootLock);
- }
- #endif
-
- /*
- * If there are no real locks on the disk, we need not keep any
- * information about it.
- */
-
- MSUnLock(RootLock); /* may call FreeLockList and free VolNode
- * (!) */
- RootLock = NULL;
-
- if (LockList) {
- *locks = LockList; /* VolNode can't be gone now... */
- LockList = NULL;
- return 0; /* not all references gone */
- } else {
- return 1; /* all gone, even the VolNode */
- }
- }
-
- void
- HanCloseDown()
- {
- #ifdef HDEBUG
- register struct MSFileLock *fl;
-
- while (LockList && (fl = (struct MSFileLock *) GetHead(&LockList->ll_List))) {
- debug(("UNLOCKING %08lx: ", fl));
- PrintDirEntry(&fl->msfl_Msd);
- MSUnLock(fl); /* Remove()s it from this List */
- }
- #endif
- if (DiskIOReq) {
- if (DiskIOReq->iotd_Req.io_Unit) {
- MSUpdate(1);
- CloseDevice(DiskIOReq);
- }
- DeleteExtIO(DiskIOReq);
- DiskIOReq = NULL;
- }
- if (TimeIOReq) {
- if (TimeIOReq->tr_node.io_Unit) {
- WaitIO(TimeIOReq);
- CloseDevice(TimeIOReq);
- }
- DeleteExtIO(TimeIOReq);
- TimeIOReq = NULL;
- }
- if (DiskReplyPort) {
- DeletePort(DiskReplyPort);
- DiskReplyPort = NULL;
- }
- if (IntuitionBase) {
- CloseLibrary(IntuitionBase);
- IntuitionBase = NULL;
- }
- }
-
- int
- HanOpenUp()
- {
- LockList = NULL;
- RootLock = NULL;
- Fat = NULL;
- IDDiskState = ID_WRITE_PROTECTED;
- IDDiskType = ID_NO_DISK_PRESENT;
- DelayState = DELAY_OFF;
- Disk.bps = MS_BPS;
- CheckBootBlock = 1;
- InitCacheList();
-
- TimeIOReq = NULL;
-
- #ifdef HDEBUG
- if (!(DiskReplyPort = CreatePort("MSH:disk.replyport", -1L)))
- goto abort;
- #else
- if (!(DiskReplyPort = CreatePort(NULL, -1L)))
- goto abort;
- #endif
-
- debug(("DiskReplyPort = 0x%08lx\n", DiskReplyPort));
-
- if (!(DiskIOReq = CreateExtIO(DiskReplyPort, (long) sizeof (*DiskIOReq)))) {
- debug(("Failed to CreateExtIO\n"));
- goto abort;
- }
- if (OpenDevice(DevName, UnitNr, DiskIOReq, DevFlags | TDF_ALLOW_NON_3_5)) {
- debug(("Failed to OpenDevice\n"));
- goto abort;
- }
- TimeIOReq = (struct timerequest *) CreateExtIO(DiskReplyPort,
- (long) sizeof (*TimeIOReq));
-
- if (TimeIOReq == NULL || OpenDevice(TIMERNAME, UNIT_VBLANK, TimeIOReq, 0L))
- goto abort;
- TimeIOReq->tr_node.io_Flags = IOF_QUICK; /* For the first WaitIO() */
-
- IntuitionBase = OpenLibrary("intuition.library", 0L);
- return DOSTRUE;
-
- abort:
- HanCloseDown();
- return 0;
- }
-
- /*
- * Relabel the disk. We create new labels if necessary.
- */
-
- long
- MSRelabel(newname)
- byte *newname;
- {
- #ifdef READONLY
- return DOSFALSE;
- #else
- /*
- * A null or empty string means: remove the label, if any.
- */
- if (!newname || !*newname) {
- if ((int) RootLock->msfl_DirSector >= (int) Disk.rootdir) {
- RootLock->msfl_Msd.msd_Name[0] = DIR_DELETED;
- RootLock->msfl_Msd.msd_Attributes = 0;
- WriteFileLock(RootLock);
- RootLock->msfl_Msd = FakeRootDirEntry.de_Msd;
- RootLock->msfl_DirSector = -1;
- Disk.vollabel = FakeRootDirEntry;
- }
- return DOSTRUE;
- }
- /*
- * No label yet? Then we must create one, even if we need to move
- * something else for it.
- */
-
- if ((int) RootLock->msfl_DirSector < 0) {
- struct MSFileLock *new;
-
- new = MSLock(RootLock, "><>.\\", EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
- if ((new == NULL) && (new = EmptyFileLock)) {
- error = 0;
- if (new->msfl_DirSector == Disk.rootdir) {
- RootLock->msfl_DirSector = Disk.rootdir;
- RootLock->msfl_DirOffset = new->msfl_DirOffset;
- } else {
- /*
- * Move something out of the first directory block. Try
- * not to move system files or directories (. ..), but
- * we'll do it if we need to. Set the root dir date to
- * now.
- */
- byte *fromsec;
- byte *tosec;
- register struct MsDirEntry *dir;
-
- fromsec = GetSec(Disk.rootdir);
- tosec = GetSec(new->msfl_DirSector);
-
- dir = (struct MsDirEntry *) fromsec;
- while (dir->msd_Attributes & (ATTR_SYSTEM | ATTR_DIRECTORY)) {
- if ((byte *) ++dir >= fromsec + Disk.bps) {
- --dir; /* Back to last entry in the block */
- break; /* and move it no matter what */
- }
- }
- CopyMem(dir, tosec + new->msfl_DirOffset,
- (long) sizeof (struct MsDirEntry));
- MarkSecDirty(tosec);
- RootLock->msfl_DirSector = Disk.rootdir;
- RootLock->msfl_DirOffset = (byte *) dir - fromsec;
-
- FreeSec(tosec);
- FreeSec(fromsec);
-
- }
- }
- EmptyFileLock = NULL;
- MSUnLock(new);
- }
- if ((int) RootLock->msfl_DirSector >= Disk.rootdir) {
- struct DateStamp dateStamp;
-
- /*
- * The easy part: Copy the name to Disk.vollabel and RootLock.
- */
- {
- register int i;
- register byte *s,
- *d;
-
- s = newname;
- d = Disk.vollabel.de_Msd.msd_Name;
- for (i = 0; i < 8 + 3; i++) {
- if (s[0])
- *d++ = ToUpper(*s++);
- else
- *d++ = ' ';
- }
- }
- DateStamp(&dateStamp);
- ToMSDate(&Disk.vollabel.de_Msd.msd_Date,
- &Disk.vollabel.de_Msd.msd_Time, &dateStamp);
- RootLock->msfl_Msd = Disk.vollabel.de_Msd; /* Just for the name and
- * date */
- WriteFileLock(RootLock);
-
- return DOSTRUE;
- }
- return DOSFALSE;
- #endif
- }
-
- #ifdef HDEBUG
-
- _abort()
- {
- HanCloseDown();
- RemTask(NULL);
- }
-
- #endif /* HDEBUG */
-